#pragma once

#include <iostream>

namespace events {


/**
 * Provides an interface for generic field IO
 */
class AbstractDataFieldIO
{
public:
	virtual void toStream(std::ostream &os) = 0;
	virtual void fromStream(std::istream &is) = 0;
};


/**
 * Generic implementation of Field IO
 */
template<typename EVENT, typename FTYPE>
class GenericDataFieldIO : public AbstractDataFieldIO {
public:
	typedef FTYPE (EVENT::*fget)(void);
	typedef void (EVENT::*fput)(const FTYPE);

private:
	EVENT&	_ev;
	fget	_get;
	fput	_put;

public:
	inline GenericDataFieldIO(EVENT &ev, fget get, fput put)
		: _ev(ev), _get(get), _put(put)
	{}

	virtual void toStream(std::ostream &os) {
		os << _ev._get();
	}

	virtual void fromStream(std::istream &is) {
		FTYPE val;
		is >> val;
		_ev._set(val);
	}
};


/**
 * A helper funcion, to resolve template parameters
 * automatically from given function arguments
 */
template<typename EVENT, typename FTYPE>
AbstractDataFieldIO * getFieldIO(EVENT &ev, FTYPE (EVENT::*fget)(void), void (EVENT::*fput)(const FTYPE)) {
	return new GenericDataFieldIO<EVENT, FTYPE>(ev, fget, fput);
}


}  // end namespace
